package com.spancer.usercenter.auth;

import com.spancer.usercenter.util.JwtOperator;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.ObjectUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * author by: mars
 * Date: 2020/11/11 13:23
 * Description: 切面：
 * 逻辑：检查用户是否登录逻辑
 * 知识点：
 * 1.SpringMvc静态获取Request
 */
@Aspect
@Component
public class AuthAspect {
    @Autowired
    private JwtOperator jwtOperator;

    // 校验token-aop
    @Around("@annotation(com.spancer.usercenter.auth.CheckLogin)")
    public Object checkLogin(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        try{
            checkToken();
        }catch (Throwable e){
            throw  new SecurityException("Token不合法");
        }
        // 4.如果合法，直接执行切面注解下的方法
        return proceedingJoinPoint.proceed();
    }

    @Around("@annotation(com.spancer.usercenter.auth.CheckAuthorization)")
    public Object checkAuth(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        try{
            // 1.验证token是否合法
            this.checkToken();
            // 2.验证角色
            HttpServletRequest request = getHttpServletRequestCommon();
            String role = (String)request.getAttribute("role");
            // request里的角色和checkAuth注解里指定的角色对比
            MethodSignature signature = (MethodSignature)proceedingJoinPoint.getSignature();
            String value = signature.getMethod().getAnnotation(CheckAuthorization.class).value();
            if ( !value.equals(role)) {
                throw  new SecurityException("不是admin角色");
            }
        }catch (Throwable e){
            throw  new SecurityException("不是admin角色，无权访问",e);
        }
        return proceedingJoinPoint.proceed();
    }

    private void checkToken() {
        // 1.hearder 中获取token
        // 1.1 如何获取header?SpringMVC静态获取Request
        HttpServletRequest request = getHttpServletRequestCommon();
        // 获取前端头部设置的 X-Token
        String token = request.getHeader("X-Token");
        // 2.校验 header里的token,校验token是否合法，如果不合法直接抛异常，如何合法即放行
        boolean isValid = jwtOperator.validateToken(token);
        if (!isValid) {
            throw new SecurityException("token校验失败");
        }
        // 3. 如果合法，将用户信息放入 HttpServletRequest 的attribute里面，进行信息的携带
        Claims claims = jwtOperator.getClaimsFromToken(token);
        request.setAttribute("id",claims.get("id"));
        request.setAttribute("wxNickName",claims.get("wxNickName"));
        request.setAttribute("role",claims.get("role"));
    }

    private HttpServletRequest getHttpServletRequestCommon() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        return request;
    }


}
